<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8">
		<meta http-equiv="X-UA-Compatible" content="IE=edge">
		<meta name="viewport" content="width=device-width, initial-scale=1.0">
		<title>02-单例模式</title>
	</head>
	<body>
		<!-- https://blog.csdn.net/qq_34870529/article/details/131612301 -->
		<script>
			{
				// 工厂模式
				// 定义一个产品类
				class Product {
					constructor(name) {
						this.name = name;
					}
					display() {
						console.log(`Product: ${this.name}`);
					}
				}
				// 定义工厂类
				class Factory {
					createProduct(name) {
						return new Product(name);
					}
				}
				// 使用工厂创建对象
				const factory = new Factory();
				const product1 = factory.createProduct('Product 1');
				const product2 = factory.createProduct('Product 2');
				product1.display();
				product2.display();
			}

			{
				// 单例模式
				class Singleton {
					static instance = null;
					constructor() {
						if (Singleton.instance) {
							return Singleton.instance;
						}
						Singleton.instance = this;
					}
				}
				// 获取实例
				const instance1 = new Singleton();
				const instance2 = new Singleton();
				console.log(instance1 === instance2);
			}

			{
				// 策略模式
				class Strategy {
					execute() {
						// 策略执行的具体操作
					}
				}
				class ConcreteStrategy1 extends Strategy {
					execute() {
						console.log('Strategy 1');
					}
				}
				class ConcreteStrategy2 extends Strategy {
					execute() {
						console.log('Strategy 2');
					}
				}
				// 使用策略
				const strategy1 = new ConcreteStrategy1();
				const strategy2 = new ConcreteStrategy2();
				strategy1.execute();
				strategy2.execute();
			}

			{
				// 代理模式
				class RealSubject {
					request() {
						console.log('Real subject request');
					}
				}
				class Proxy {
					constructor(fn) {
						this.realSubject = fn;
					}
					request() {
						// 在调用真实对象方法之前或之后执行额外操作
						console.log('Proxy request');
						this.realSubject.request();
					}
				}
				// 使用代理
				const realSubject = new RealSubject();
				const proxy = new Proxy(realSubject);
				proxy.request();
			}

			{
				// 观察者模式
				class Subject {
					constructor() {
						this.observers = [];
					}
					addObserver(observer) {
						this.observers.push(observer);
					}
					removeObserver(observer) {
						this.observers = this.observers.filter(obs => obs !== observer);
					}
					notifyObservers() {
						this.observers.forEach(observer => observer.update());
					}
				}
				class Observer {
					constructor(name) {
						this.name = name;
					}
					update() {
						console.log(`Observer ${this.name} has been notified.`);
					}
				}
				// 创建主题和观察者
				const subject = new Subject();
				const observer1 = new Observer('1');
				const observer2 = new Observer('2');
				// 注册观察者
				subject.addObserver(observer1);
				subject.addObserver(observer2);
				// 通知观察者
				subject.notifyObservers();
			}

			{
				// 发布订阅模式
				class EventBus {
					constructor() {
						this.subscribers = {};
					}
					subscribe(eventName, callback) {
						if (!this.subscribers[eventName]) {
							this.subscribers[eventName] = [];
						}
						this.subscribers[eventName].push(callback);
					}
					unsubscribe(eventName, callback) {
						if (this.subscribers[eventName]) {
							this.subscribers[eventName] = this.subscribers[eventName].filter((cb) => cb !== callback);
						}
					}
					publish(eventName, data) {
						if (this.subscribers[eventName]) {
							this.subscribers[eventName].forEach(callback => callback(data));
						}
					}
				}
				// 创建事件总线
				const eventBus = new EventBus();
				// 订阅事件
				const callback1 = (data) => console.log(`Subscriber 1 received: ${data}`);
				const callback2 = (data) => console.log(`Subscriber 2 received: ${data}`);
				eventBus.subscribe('event1', callback1);
				eventBus.subscribe('event2', callback2);
				// 发布事件
				eventBus.publish('event1', 'Hello subscribers 1!');
				eventBus.publish('event2', 'Hello subscribers 2!');
			}

			{
				// 原型模式
				class Prototype {
					constructor(name) {
						this.name = name;
					}
					clone() {
						return Object.create(Object.getPrototypeOf(this));
					}
				}
				// 创建原型对象
				const prototype = new Prototype('Prototype');
				// 克隆对象
				const clone1 = prototype.clone();
				const clone2 = prototype.clone();
				console.log(clone1.name);
				console.log(clone2.name);
			}
		</script>
	</body>
</html>